<template>
  <div>
    <div v-if="!showView">
      <el-row :gutter="10" justify="center">
        <el-col :xs="18" :sm="18" :md="5" :lg="5" :xl="5">
          <div style="height:100vh;display: flex;flex-direction: column;justify-content: space-between">
            <div>
              <div style="margin-top:10vh;text-align: left;margin-bottom: 10px;font-size:  25px;font-weight: bold">
                设备端！
              </div>
              <div style="text-align: left;margin-bottom: 30px;font-size:  25px;font-weight: bold">
                欢迎来到宠之语
              </div>

              <div style="text-align: left;margin-bottom: 10px;font-size:  12px;font-weight: bold">
                请输入对应设备名称
              </div>
              <el-input
                  v-model="deviceName"
                  placeholder="设备名称"
                  size="large"
              >
                <template #append>
                  <el-button :icon="CheckIcon" @click="checkName"/>
                </template>
              </el-input>

            </div>

            <el-image style="width: 100%;" :src="src" fit="fill"/>

          </div>
        </el-col>
      </el-row>
    </div>
    <video v-else id="local-video" autoplay playsinline muted></video>
  </div>
</template>

<style>
#local-video {
  width: 300px;
  height: auto;
}
</style>

<script>
import {ref, onMounted, toRefs, reactive} from 'vue';
import io from 'socket.io-client';
// import {baseURL} from '@/config'
import {ElNotification} from "element-plus";
import {sendDeviceName} from "@/api/role";

import {Check} from '@element-plus/icons-vue'

export default {
  name: "deviceView",
  setup() {
    const state = reactive({
      deviceName: "1",
      targetId: "",
      showView: false,
      src: require("@/assets/monitor.png"),
    })

    let socket = ref(null);
    onMounted(() => {
    })
    const checkName = async () => {
      if (!state.deviceName) {
        ElNotification({
          title: '提示',
          message: "名称不能为空",
          type: 'warning',
        })
      } else {
        //密码输入有误，请确认令牌是否正确
        const {data} = await sendDeviceName({deviceName: state.deviceName})
        console.log(data)
        if (data) {
          if (data) {
            ElNotification({
              title: '恭喜!',
              message: "连接成功,不要刷新哦，请稍等...",
              type: 'success',
            })
            state.showView = true
            await connect()
          }
        } else {
          ElNotification({
            title: '提示',
            message: "密码有误请再次尝试",
            type: 'warning',
          })
        }
      }
    }

    const initRTC = async () => {
      // 如果之前已经有 'answer' 事件的监听器，先移除它
      if (socket.value._callbacks && socket.value._callbacks['$answer']) {
        socket.value.off('answer');
        socket.value.off('candidate');
        socket.value.off('client_disconnected');
      }

      // 创建一个 RTCPeerConnection
      // const pc = new RTCPeerConnection();
      const pc = new RTCPeerConnection({
        iceServers: [
          {
            urls: 'stun:82.156.207.54:3478' // 这是你自己的 STUN 服务器
          },
          {
            urls: 'turn:82.156.207.54:3478', // 这也是你自己的 TURN 服务器
            username: 'admin',
            credential: 'petcode'
          }
        ]
      });

      pcs.set(state.targetId, pc)

      // 将获取到的音视频流添加到 RTCPeerConnection 中
      stream.getTracks().forEach(track => pc.addTrack(track, stream));

      pc.createOffer()
          .then(offer => pc.setLocalDescription(offer))
          .then(() => {
            socket.value.emit('offer', pc.localDescription, state.targetId)

            console.log(state.targetId)
            // 当接收到客户端的 answer 时，保存到 RTCPeerConnection 中
          });

      // 当 RTCPeerConnection 有新的 ICE candidate 时，发送给服务器
      pc.onicecandidate = event => {
        if (event.candidate) {
          console.log("发送新的 ICE candidate: ", event.candidate);
          socket.value.emit('candidate', event.candidate, {
            type: 'device',
            token: state.targetId
          });
        }
      };

      pc.onerror = (event) => {
        console.error("RTCPeerConnection encountered an error: ", event);
      };

      // TODO 可能导致上一个answer事件出问题
      socket.value.on('answer', (answer) => {
        console.log("设备端收到answer现在开始设置客户端为远程描述文件")
        pc.setRemoteDescription(new RTCSessionDescription(answer));
      });

      // 当从服务器收到新的 ICE candidate 时，添加到 RTCPeerConnection
      socket.value.on('candidate', (candidate) => {
        console.log("添加新的 ICE candidate 到 RTCPeerConnection: ", candidate);
        if (pc.signalingState !== 'closed') pc.addIceCandidate(new RTCIceCandidate(candidate));
      });

      // 设备端代码，当收到 client_disconnected 消息时，关闭对应的 RTCPeerConnection
      socket.value.on('client_disconnected', (clientId) => {
        console.log("关闭一位客户端。。。" + clientId)
        const pc = pcs.get(clientId);
        pc.onicecandidate = null;
        pc.close();
        pcs.delete(clientId);
        console.log("关闭通道" + pc)

      });
    }

    const pcs = new Map()
    let stream

    const connect = async () => {
      // 获取音视频流
      const constraints = {
        video: {
          facingMode: 'environment', // 使用后置摄像头
          width: {ideal: 800}, // 理想宽度640px
          height: {ideal: 600}, // 理想高度480px
          frameRate: {ideal: 50} // 帧率45fps
        },
        audio: true
      };
      stream = await navigator.mediaDevices.getUserMedia(constraints);
      // 使用这个流做一些事，比如显示在一个<video>元素中
      const localVideo = document.querySelector('#local-video');
      if (localVideo) localVideo.srcObject = stream;

      // 创建一个 Socket.IO 连接
      // socket.value = io("https://petcode.wang");
      socket.value = io("https://stun.ggiooo.com:3000");

      // 标识自己为设备端
      socket.value.emit('device_Online', state.deviceName);


      // 当接收到服务器的 client_connected 消息时，创建并发送 offer
      socket.value.on('client_connected', (targetId) => {
        console.log("开始发送本地描述文件给客户端")
        state.targetId = targetId
        initRTC()
      });
      // socket断连删除RTC通道、设备过多发送删除RTC通道、测试ios是否ok
    };

    return {...toRefs(state), socket, checkName, connect, CheckIcon: Check};
  }
};
</script>
